﻿namespace NTLib.Pipe.Containers
{
    using NTLib.Core.Pool;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using NTLib.Pipe.Targets;
    using NTLib.Core.Threading;
    using NTLib.Core.Collection;
    using System.Threading;
    using System.Diagnostics;
    using NTLib.Pipe.Descriptors;
    using NTLib.Pipe.Exceptions;



    /// <summary>
    /// Pipe that will stored the data on the local memory AppDomain
    /// ThreadSafe
    /// </summary>
    /// <typeparam name="T">Data to stored</typeparam>
    public class MemoryPipeSource<T> : BasePipeSourcePoolItem<T, LocalTargetDescription>
    {
        #region Fields

        private readonly Queue<T> _items;
        //private readonly Dictionary<T, Queue<TaskCompletionSource<object>>> _waiter;
        //private readonly Dictionary<TaskCompletionSource<object>, CancellationToken> _waiterCancel;

        #endregion

        #region Ctor

        /// <summary>
        /// Initializes a new instance of the <see cref="MemoryPipeSource{T}"/> class.
        /// </summary>
        public MemoryPipeSource()
        {
            this._items = new Queue<T>();
            //this._waiter = new Dictionary<T, Queue<TaskCompletionSource<object>>>();
            //this._waiterCancel = new Dictionary<TaskCompletionSource<object>, CancellationToken>();
        }

        #endregion

        #region Properties
        
        /// <summary>
        /// Gets a value indicating whether this instance can pop item.
        /// </summary>
        /// <value>
        /// <c>true</c> if this instance can pop item; otherwise, <c>false</c>.
        /// </value>
        public override bool CanPopItem
        {
            get
            {
                base.CheckSourceIsInitialized();
                return true;
            }
        }

        /// <summary>
        /// Gets the value indicating that the current pipe allow the user to push items through it.
        /// </summary>
        /// <value>
        /// s
        /// <c>true</c> if this instance can push item; otherwise, <c>false</c>.
        /// </value>
        public override bool CanPushItem
        {
            get
            {
                base.CheckSourceIsInitialized();
                return true;
            }
        }

        #endregion

        #region Methods

        /// <summary>
        /// Called when the update pop waiter is called.
        /// This methods is used to dequeue item from the queue to the waiter.
        /// The call is thread safe.
        /// </summary>
        /// <returns>An item</returns>
        protected override Task<T> OnDequeueItemAsync(CancellationToken unUsed)
        {
            if (this._items.Count > 0)
            {
                var item = this._items.Dequeue();

                //Queue<TaskCompletionSource<object>> waiter = null;

                //if (this._waiter.TryGetValue(item, out waiter))
                //{
                //    TaskCompletionSource<object> wait = null;
                //    bool loop = false;

                //    do
                //    {
                //        loop = false;
                //        wait = null;
                //        if (waiter.Count > 0)
                //        {
                //            wait = waiter.Dequeue();
                //            CancellationToken token = default(CancellationToken);
                //            if (this._waiterCancel.TryGetValue(wait, out token))
                //            {
                //                if (token.IsCancellationRequested)
                //                    loop = true;
                //            }
                //        }
                //    }
                //    while (loop);

                //    if (wait != null)
                //        wait.SetResult(true);
                //}
                return Task.FromResult(item);
            }
            return Task.FromResult(default(T));
        }

        /// <summary>
        /// Pushes the item on the storage system without waiting any response.
        /// The call is thread safe.
        /// </summary>
        /// <param name="item"></param>
        protected override async Task OnSend(T item, CancellationToken token)
        {
            this._items.Enqueue(item);
            await Task.Yield();
        }

        #endregion
    }
}
